package com.seres.backend.admin;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import com.seres.data.AceCategory;

public class AcesParser {
	private static final int FULL_DESCRIPTION_COL_NR = 1+3;
	private static final int SHORT_DESCRIPTION_COL_NR = 2+3;
	private static final int CATEGORY_ID_COL_NR = 3+3;
	private static final int RISK_IMPACT_COL_NR = 4+3;
	private static final int STAKEHOLDER_ID_IMPACT_COL_NR = 6+3;	
	private static final int IMPACT_SCORE_COL_NR = 6+3;
	
	private static final int ACES_BLOCK_LENGTH = 2;
	
	private static final int ACE_CATEGORY_ID_COL_NR = 1+3;
	private static final int ACE_CATEGORY_NAME_COL_NR = 2+3;
	private static final int MAX_NR_OF_ACE_CATEGORIES = 10;
	private static final int ACE_CATEGORY_START_ROW_NR = 3;
	
	private static final int TITLE_COL_NR = 1+3;
	private static final int TITLE_ROW_NR = 14;
	private static final String TITLE = "aces";
	
	private static final int DATA_START_ROW_NR = 15;
	
	private boolean dataEndReached = false;
	
	private XSSFSheet worksheet;
	private List<Integer> allowedStakeholderIds;
	
	public AcesParser(XSSFSheet worksheet, List<Integer> allowedStakeholderIds){
		setWorksheet(worksheet);
		setAllowedStakeholderIds(allowedStakeholderIds);
	}
	public AcesParserResult parse(){
		AcesParserResult result = new AcesParserResult();
		List<AceCategoryLine> aceCategoryLines = parseAceCategories();
		result.setAceCategoryLines(aceCategoryLines);
		
		List<Integer> stakeholderIDs = null;
		
		for(int i = 0; !isDataEndReached(); i++){
			System.out.println("isDataEndReached: " + isDataEndReached());
			
			List<Integer> impactScores;
			String shortDescription;
			String fullDescription;
			int categoryId;
			int riskImpact;
			
			for(int j = 0; j < ACES_BLOCK_LENGTH; j++){
				XSSFRow row = getWorksheet().getRow(DATA_START_ROW_NR + (i*(ACES_BLOCK_LENGTH)) + j);	
				
				if(j == 0){
					stakeholderIDs = parseStakeholderIDs(row);
					
					//print list
					System.out.println("*** stakeholder ids block " + i + " ***");
					for(int k = 0; k < stakeholderIDs.size(); k++){
						System.out.println("ID: " + stakeholderIDs.get(k));
					}
					System.out.println("*** end stakeholder ids list ***");
				}
				else if(j == 1){
					if(containsData(row.getCell(FULL_DESCRIPTION_COL_NR))){ //contains full description
						System.out.println("containsData(row.getCell(FULL_DESCRIPTION_COL_NR)): " + containsData(row.getCell(FULL_DESCRIPTION_COL_NR)));
						System.out.println(parseFullDescription(row.getCell(FULL_DESCRIPTION_COL_NR)));
						categoryId = parseCategoryId(row.getCell(CATEGORY_ID_COL_NR));
						if(canHaveAsCategoryId(aceCategoryLines,categoryId)){
							fullDescription = parseFullDescription(row.getCell(FULL_DESCRIPTION_COL_NR));
							shortDescription = parseShortDescription(row.getCell(SHORT_DESCRIPTION_COL_NR));
							riskImpact = parseImpact(row.getCell(RISK_IMPACT_COL_NR));
							impactScores = parseImpactScores(row);
							System.out.println("fullDescription: " + fullDescription);
							System.out.println("shortDescription: " + shortDescription);
							System.out.println("categoryId: " + categoryId);
							System.out.println("riskImpact: " + riskImpact);
							//print impact scores
							System.out.println("*** impact scores block " + i + " row " + j + " ***");
							for(int k = 0; k < impactScores.size(); k++){
								System.out.println("score: " + impactScores.get(k));
							}
							System.out.println("*** end impact scores list ***");
							
							result.addAceLine(new AceLine(categoryId,fullDescription,shortDescription,riskImpact,stakeholderIDs,impactScores));
						}
					}
					else{
						setDataEndReached(true);
						System.out.println("setDataEndReached");
					}
				}
							
			}
		}
		return result;
	}

	private boolean canHaveAsCategoryId(List<AceCategoryLine> aceCategoryLines,
			int categoryId) {
		for(AceCategoryLine line : aceCategoryLines){
			if(line.getAceCategoryId() == categoryId){
				return true;
			}
		}
		return false;
	}
	private List<AceCategoryLine> parseAceCategories() {
		List<AceCategoryLine> aceCategoryLines = new ArrayList<AceCategoryLine>();
		boolean endReached = false;
		
		for(int i = 0; i < MAX_NR_OF_ACE_CATEGORIES && !endReached; i++){
			if(containsData(getWorksheet().getRow(ACE_CATEGORY_START_ROW_NR + i).getCell(ACE_CATEGORY_ID_COL_NR))){
				int aceCategoryId = parseAceCategoryId(getWorksheet().getRow(ACE_CATEGORY_START_ROW_NR + i).getCell(ACE_CATEGORY_ID_COL_NR));
				String aceCategoryName = parseAceCategoryName(getWorksheet().getRow(ACE_CATEGORY_START_ROW_NR + i).getCell(ACE_CATEGORY_NAME_COL_NR));
				aceCategoryLines.add(new AceCategoryLine(aceCategoryId,aceCategoryName));
				System.out.println("aceCategoryId: " + aceCategoryId);
				System.out.println("aceCategoryName: " + aceCategoryName);
			}
			else{
				endReached = true;
			}
		}
		return aceCategoryLines;
	}
	private String parseAceCategoryName(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid ace category name cell");
		}
	}
	private int parseAceCategoryId(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid ace category id cell");
		}
	}
	private List<Integer> parseStakeholderIDs(XSSFRow row) {
		List<Integer> stakeholderIds = new ArrayList<Integer>();
		boolean stakeholderIDsEndReached = false;
		int i = 0;
		while(!stakeholderIDsEndReached){
			if(containsData(row.getCell(STAKEHOLDER_ID_IMPACT_COL_NR + i))){ // contains stakeholder id
				stakeholderIds.add(parseStakeholderId(row.getCell(STAKEHOLDER_ID_IMPACT_COL_NR + i)));
			}
			else{
				stakeholderIDsEndReached = true;
			}
			i++;
		}
		return stakeholderIds;
	}
	private List<Integer> parseImpactScores(XSSFRow row) {
		List<Integer> impactScores = new ArrayList<Integer>();
		boolean impactScoresEndReached = false;
		int i = 0;
		while(!impactScoresEndReached){
			if(containsData(row.getCell(IMPACT_SCORE_COL_NR + i))){ // contains impact score
				impactScores.add(parseImpact(row.getCell(IMPACT_SCORE_COL_NR + i)));
			}
			else{
				impactScoresEndReached = true;
			}
			i++;
		}
		return impactScores;
	}
	private int parseImpact(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid impact cell");
		}
	}	

	private String parseFullDescription(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid full description cell");
		}
	}
	private String parseShortDescription(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_STRING){
			return cell.getStringCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid short description cell");
		}
	}

	private int parseCategoryId(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid category id cell");
		}
	}
	private int parseStakeholderId(XSSFCell cell){
		System.out.println("stak");
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC && canHaveAsStakeholderId((int) cell.getNumericCellValue())){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid stakeholder id cell");
		}
	}
	private boolean containsData(XSSFCell cell){
		return cell.getCellType() != Cell.CELL_TYPE_BLANK;
	}
	private boolean isDataEndReached() {
		return dataEndReached;
	}
	private void setDataEndReached(boolean dataEndReached) {
		this.dataEndReached = dataEndReached;
	}
	private XSSFSheet getWorksheet() {
		return worksheet;
	}
	public boolean canHaveAsWorksheet(XSSFSheet worksheet){
		return worksheet.getRow(TITLE_ROW_NR).getCell(TITLE_COL_NR).getStringCellValue().toLowerCase().equals(TITLE);
	}
	private void setWorksheet(XSSFSheet worksheet) {
		if(canHaveAsWorksheet(worksheet)){
			this.worksheet = worksheet;
		}
		else{
			throw new IllegalArgumentException("invalid modules worksheet");
		}
		
	}
	private boolean canHaveAsStakeholderId(int numericCellValue) {
		return getAllowedStakeholderIds().contains(numericCellValue);
	}
	private void setAllowedStakeholderIds(List<Integer> allowedStakeholderIds) {
		this.allowedStakeholderIds = allowedStakeholderIds;
	}
	public List<Integer> getAllowedStakeholderIds() {
		return allowedStakeholderIds;
	}
}
